package lrc2video.happy.lyrics.formats.ass;

import lombok.extern.log4j.Log4j2;
import lrc2video.happy.lyrics.LyricsFileReader;
import lrc2video.happy.lyrics.model.LyricsInfo;
import lrc2video.happy.lyrics.model.LyricsLineInfo;
import lrc2video.happy.lyrics.model.LyricsTag;
import lrc2video.happy.lyrics.utils.TimeUtils;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 解析ass文件成歌词对象信息
 */
@Log4j2
public class AssLyricsFileReader extends LyricsFileReader {
    @Override
    public LyricsInfo readLrcText(String dynamicContent, String lrcContent, String extraLrcContent, String lyricsFilePath) throws Exception {
        return null;
    }

    @Override
    public LyricsInfo readInputStream(InputStream in, double mp3TimeLength) throws Exception {
        LyricsInfo lyricsIfno = new LyricsInfo();
        lyricsIfno.setTimeLength(mp3TimeLength);
        lyricsIfno.setLyricsFileExt(getSupportFileExt());
        if (in != null) {
            BufferedReader br = new BufferedReader(new InputStreamReader(in,
                    getDefaultCharset()));

            // 这里面key为该行歌词的开始时间，方便后面排序
            SortedMap<Integer, LyricsLineInfo> lyricsLineInfosTemp = new TreeMap<Integer, LyricsLineInfo>();
            Map<String, Object> lyricsTags = new HashMap<String, Object>();
            String lineInfo = "";
            boolean inEventsSection = false;
            while ((lineInfo = br.readLine()) != null) {
                if (lineInfo.trim().equals("[Events]")) {
                    inEventsSection = true;
                    continue;
                }
                if (!inEventsSection) continue;
                // 解析歌词
                parserLineInfos(lyricsLineInfosTemp,
                        lyricsTags, lineInfo);

            }
            in.close();
            in = null;
            // 重新封装
            TreeMap<Integer, LyricsLineInfo> lyricsLineInfos = new TreeMap<Integer, LyricsLineInfo>();
            int index = 0;
            Iterator<Integer> it = lyricsLineInfosTemp.keySet().iterator();
            while (it.hasNext()) {
                lyricsLineInfos
                        .put(index++, lyricsLineInfosTemp.get(it.next()));
            }
            it = null;
            // 设置歌词的标签类
            lyricsIfno.setLyricsTags(lyricsTags);
            //
            lyricsIfno.setLyricsLineInfoTreeMap(lyricsLineInfos);
        }
        return lyricsIfno;
    }

    private void parserLineInfos(SortedMap<Integer, LyricsLineInfo> lyricsLineInfosTemp, Map<String, Object> lyricsTags, String lineInfo) {
        // 解析到一行对话 也就是歌词
        if (lineInfo.startsWith("Dialogue:")) {
            String[] parts = lineInfo.split(",", 10);
            if (parts.length == 10) {
                LyricsLineInfo lyricsLineInfo = new LyricsLineInfo();
                String startTimeStr = parts[1].trim();
                String endTimeStr = parts[2].trim();
                // 0:00:00.00
                lyricsLineInfo.setStartTime(TimeUtils.parseInteger(startTimeStr));
                lyricsLineInfo.setEndTime(TimeUtils.parseInteger(endTimeStr));
                // 提取并清理歌词文本，同时提取每个字符的显示时间
                // {\K40}她{\K42}给{\K37}的{\K32}永{\K275}远 {\K26}不{\K161}重
                String lyricsWithTags = parts[9];
                Pattern kPattern = Pattern.compile("\\{\\\\K(\\d+)}");
                Matcher matcher = kPattern.matcher(lyricsWithTags);
//                  <时间长度>代表在下一小段出现高亮效果之前的当前段高亮停留时间, 值为百分之一秒的倍数
//　　　　　　　　　   \k<时间长度>按照每一分隔好的小段来进行高亮显示
                List<Integer> durations = new ArrayList<>(); // 这里是ms
                StringBuffer cleanedLyricsBuffer = new StringBuffer();
                String regex = "__zhixin__";
                while (matcher.find()) {
                    String group = matcher.group(1);
                    durations.add(Integer.parseInt(group) * 10);
                    matcher.appendReplacement(cleanedLyricsBuffer, regex);
                }
                matcher.appendTail(cleanedLyricsBuffer);
                if (durations.size() == 0) {
                    int length = cleanedLyricsBuffer.length();
                    if (length == 0) {
                        length = 1;
                        cleanedLyricsBuffer.append(" ");
                    }
                    int timeAvg = (lyricsLineInfo.getEndTime() - lyricsLineInfo.getStartTime()) / length;
                    for (int i = 0; i < length; i++) {
                        // 这里计算平均不用管
                        durations.add(timeAvg);
                    }
                    lyricsLineInfo.setLineLyrics(cleanedLyricsBuffer.toString());
                    lyricsLineInfo.setLyricsWords(cleanedLyricsBuffer.toString().split(""));
                } else {
                    String substring = cleanedLyricsBuffer.substring(regex.length());
                    lyricsLineInfo.setLineLyrics(substring.replaceAll(regex, ""));
                    lyricsLineInfo.setLyricsWords(substring.split(regex));
                }
                lyricsLineInfo.setWordsDisInterval(durations);
                if (lyricsLineInfo.getWordsDisInterval().length != lyricsLineInfo.getLyricsWords().length) {
                    log.info("lyricsLineInfo.getWordsDisInterval() = " + Arrays.toString(lyricsLineInfo.getWordsDisInterval()));
                    log.info("lyricsLineInfo.getLyricsWords() = " + Arrays.toString(lyricsLineInfo.getLyricsWords()));
                    log.info("lyricsLineInfo.getLineLyrics() = " + lyricsLineInfo.getLineLyrics());
                    System.exit(130);
                }
                lyricsLineInfosTemp.put(lyricsLineInfo.getStartTime(), lyricsLineInfo);
            } else {
                log.info("Invalid Dialogue line format.");
            }
        }
    }

    @Override
    public boolean isFileSupported(String ext) {
        return ext.equalsIgnoreCase("ass");
    }

    @Override
    public String getSupportFileExt() {
        return "ass";
    }
}
